﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using XuLyDuLieu.ClassDetails;

namespace XuLyDuLieu.Core
{
    public class Example_2 : DataProcessing
    {
        #region "[Nhận dạng kiểu chia trong giỏ]"
        public override DataProcessing.KieuChia NhanDangKieuChia(bool _isKieuChia)
        {
            KieuChia kieuChia = KieuChia.NULL;
            try {

                if (_isKieuChia)
                    kieuChia = KieuChia.TheoChieuRong;
                else
                    kieuChia = KieuChia.TheoChieuSau;
            }
            catch { }
            return kieuChia;
        }
        #endregion

        #region "[đọc file CSV trả ra danh sách chuỗi]"
        /// <summary>
        /// doc file csv
        /// </summary>
        /// <param name="_strPath">đường dẫn file</param>
        /// <returns></returns>
        public override List<string> DocFileCSV(string _strPath)
        {
            List<string> listString = new List<string>();
            try {
                StreamReader reader = new StreamReader(_strPath);
                while (reader.EndOfStream == false)
                {
                    listString.Add(reader.ReadLine());
                }
                reader.Close();
            }
            catch { }
            return listString;
        }
        #endregion

        #region "[kiểm tra chuỗi nhập vào có phải là số hay không]"
        /// <summary>
        /// kiểm tra chuỗi nhập vào có phải là số hay không
        /// kết quả true: là số, false: khong phai so
        /// </summary>
        /// <param name="_strInput">chuỗi cần kiểm tra</param>
        /// <returns></returns>
        public override bool KiemTraKieuSo(string _strInput)
        {
            bool isSuccess = false;
            try {
                if (_strInput.Trim() == "?")
                    return true;
                double dCheck = 0;
                isSuccess = double.TryParse(_strInput, out dCheck);
            }
            catch { }
            return isSuccess;
        }
        #endregion

        #region "[Lấy thông tin 1 đối tượng từ chuỗi]"
        /// <summary>
        /// Lấy thông tin 1 đối tượng từ chuỗi
        /// </summary>
        /// <param name="_strInput">chuỗi đầu vào</param>
        /// <returns></returns>
        public override DoiTuong LayThongTinDoiTuongTuChuoi(string _strInput)
        {
            DoiTuong iResult = new DoiTuong();
            try {
                iResult.TenDoiTuong = _strInput;
                ///kiểm tra nó có phải kiểu số hay không.Nếu không
                ///thì ta đưa nó về kiểu chuỗi
                if (KiemTraKieuSo(_strInput))
                    iResult.KieuDuLieu = KieuDuLieu.Numeric;//kiểu số
                else
                    iResult.KieuDuLieu = KieuDuLieu.Nominal;//không phải kiểu số
            }
            catch { }
            return iResult;
        }
        #endregion

        #region "[lấy danh sách các thông tin của 1 đối tượng]"
        /// <summary>
        /// lấy danh sách các thông tin của 1 đối tượng
        /// </summary>
        /// <param name="_strContent"></param>
        /// <returns></returns>
        public override List<ClassDetails.DoiTuong> LayDanhSachCacDoiTuong(string _strContent)
        {
            List<ClassDetails.DoiTuong> listObj = new List<ClassDetails.DoiTuong>();
            try
            {
                Regex re = new Regex(@"\,");

                //lấy danh sách các dấu phẩy
                MatchCollection mc = re.Matches(_strContent);
                if (mc.Count > 0)
                {

                    //tách từng phần tử bên trong chuỗi.
                    int irun = 0;
                   
                    foreach (Match m in mc)
                    {
                        string temp = _strContent.Substring(irun, m.Index - irun);
                        irun = m.Index+1;//cập nhật lại irun

                        listObj.Add(LayThongTinDoiTuongTuChuoi(temp));
                    }

                    string tempLast = _strContent.Substring(irun);
                    listObj.Add(LayThongTinDoiTuongTuChuoi( tempLast));
                }
            }
            catch { }
            return listObj;
        }
        #endregion

        #region "[lấy danh sách các cột trong bảng dữ liệu]"
        /// <summary>
        /// lấy danh sách các cột trong bảng dữ liệu
        /// </summary>
        /// <param name="_listContent">nội dung dữ liệu</param>
        /// <returns></returns>
        public override List<Cot> LayDanhSachCacCot(List<string> _listContent)
        {
            List<Cot> listCots = new List<Cot>();
            try {
                if (_listContent.Count > 0)
                {
                    //lấy thống tin dòng đầu tiên để kiềm tra có bao nhiêu thuộc tính
                    string Title = _listContent[0];

                    //khai báo danh sách các dòng dữ liệu
                    List<Dong> ListDongs = new List<Dong>();
                    int SoThuocTinh = 0;
                    //kiểm tra thông tin trong các mẫu
                    for (int i = 1; i < _listContent.Count; i++)
                    {
                        //Lấy danh sách các phần tử trong 1 dòng
                        List<DoiTuong> listDoiTuong = LayDanhSachCacDoiTuong(_listContent[i]);
                        if (listDoiTuong.Count > 0)
                        {
                            //lấy danh sách số thược tính
                            SoThuocTinh = listDoiTuong.Count;

                            //danh sách các đối tượng tồn tại
                            Dong ItemDong = new Dong();
                            ItemDong.PhanTu = listDoiTuong;
                            ListDongs.Add(ItemDong);
                        }
                    }

                    if (ListDongs.Count > 0)
                    { 
                        ///Có được danh sách các dòng.
                        ///chuyển thành danh sách các cột
                        ///
                        for (int i = 0; i < SoThuocTinh; i++)
                        {
                            Cot ItemCot = new Cot();
                            KieuDuLieu kieuDuLieu = KieuDuLieu.Numeric;
                            foreach (Dong ItemRun in ListDongs)
                            {   
                                ItemCot.PhanTu.Add(ItemRun.PhanTu[i]);
                                if (kieuDuLieu == KieuDuLieu.Numeric)
                                    kieuDuLieu = ItemRun.PhanTu[i].KieuDuLieu;
                            }
                            ItemCot.KieuDuLieu = kieuDuLieu;
                            listCots.Add(ItemCot);
                        }
                    }
                }
            }
            catch { }
            return listCots;
        }
        #endregion

        #region "[Lấy danh sách các thuộc tính của dữ liệu]"
        /// <summary>
        /// Lấy danh sách các thuộc tính của dữ liệu
        /// </summary>
        /// <param name="_strTitle">dòng chứa thuộc tính</param>
        /// <returns></returns>
        public override List<string> DanhSachThuocTinh(string _strTitle)
        {
            List<string> listResult = new List<string>();
            try {
                listResult = _strTitle.Split(',').ToList();

            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[tính trung bình cộng của dãy số]"
        /// <summary>
        /// tính trung bình cộng của dãy số
        /// </summary>
        /// <param name="_listInput">dãy số cần tính</param>
        /// <returns></returns>
        public override double TrungBinhCong(List<double> _listInput)
        {
            double dResult=0;
            try {
                foreach (double Item in _listInput)
                    dResult += Item;
                dResult /= _listInput.Count;
            }
            catch { }
            return dResult;
        }
        #endregion

        #region "[kiểm tra một phần tử có xuất hiện trong mảng hay không]"
        /// <summary>
        /// kiểm tra một phần tử có xuất hiện trong mảng hay không
        /// </summary>
        /// <param name="_list">màng đối tượng</param>
        /// <param name="_ItemCheck">đối tượng cần kiểm tra</param>
        /// <returns></returns>
        public override bool KiemTraPhanTuXuatHienTrongMang(List<XuatHien> _list, DoiTuong _ItemCheck)
        {
            bool isSuccess = false;
            try {
                foreach (XuatHien Item in _list)
                {
                    if (Item.TenThuocTinh.ToLower().CompareTo(_ItemCheck.TenDoiTuong.ToLower()) == 0)
                        return true;
                }
            }
            catch { }
            return isSuccess;
        }
        #endregion

        #region "[tìm tần số xuất hiện của từng đối tượng]"
        /// <summary>
        /// tìm tần số xuất hiện của từng đối tượng
        /// </summary>
        /// <param name="_listDoiTuong">danh sách các đối tượng</param>
        /// <returns></returns>
        public override List<XuatHien> TimTanSoXuatHienCuaDoiTuong(List<DoiTuong> _listDoiTuong)
        {
            List<XuatHien> list = new List<XuatHien>();
            try
            {
                foreach (DoiTuong Item in _listDoiTuong)
                {
                    if (Item.TenDoiTuong.Trim().CompareTo("?") != 0)
                    {

                        //kiem tra xem thuoc tinh nay đã xuất hiện bao giờ hay chưa
                        if (KiemTraPhanTuXuatHienTrongMang(list, Item))
                        {
                            #region "[Tăng số lần xuất hiện của 1 phần tử trong mảng]"
                            //nếu có rồi thì tăng số lần xuất hiện lên 1
                            XuatHien ItemCheck = null;
                            try
                            {
                                ItemCheck = list.Where(p => p.TenThuocTinh.Trim().ToLower().CompareTo(Item.TenDoiTuong.ToLower().Trim()) == 0).FirstOrDefault();
                            }
                            catch { }
                            if (ItemCheck != null)
                            {
                                ItemCheck.SoLanXuatHien++;
                            }
                            #endregion
                        }
                        else
                        {
                            //nếu chưa có thì số lần xuất hiện là 1 và thêm vào list
                            XuatHien xuathien = new XuatHien();
                            xuathien.SoLanXuatHien = 1;
                            xuathien.TenThuocTinh = Item.TenDoiTuong;
                            list.Add(xuathien);
                        }
                    }

                }
            }
            catch { }
            return list;
        }
        #endregion

        #region "[tìm thuộc tính xuất hiện nhiều nhất]"
        /// <summary>
        /// tìm thuộc tính xuất hiện nhiều nhất
        /// </summary>
        /// <param name="_listDoiTuong">danh sách các đối tượng</param>
        /// <returns></returns>
        public override string TimThuocTinhXuatHienNhieuNhat(List<DoiTuong> _listDoiTuong)
        {
            string strResult = string.Empty;
            try {
                List<XuatHien> list = TimTanSoXuatHienCuaDoiTuong(_listDoiTuong);
                

                //tìm số thuộc tính xuất hiện nhiều nhất.
                XuatHien xuatHienMax = list[0];
               
                foreach (XuatHien It in list)
                {
                    if (It.SoLanXuatHien > xuatHienMax.SoLanXuatHien)
                        xuatHienMax = It;
                }
                strResult = xuatHienMax.TenThuocTinh;
            }
            catch { }
            return strResult;
        }
        #endregion

        #region "[Tìm tần số xuất hiện của đối tượng]"
        /// <summary>
        /// <para>Tìm tần số xuất hiện của đối tượng</para>
        /// <para>danh sách các đối tượng phải được sắp theo thứ tự tăng dần theo miền</para> 
        /// <para>giá trị trước khi truyền vào</para>
        /// </summary>
        /// <param name="_listDoiTuongTemps">đối tượng cần tìm</param>
        /// <returns></returns>
        public override List<XuatHien> GomNhomDoiTuongKieuNumeric(List<DoiTuong> _listDoiTuongTemps)
        {
            List<XuatHien> listResult = new List<XuatHien>();
            try {
                List<double> listDouble = _listDoiTuongTemps.Select(p => double.Parse(p.TenDoiTuong)).ToList();
                //tính số lần xuất hiện của phần tử trong mảng bằng linq
                var result = from id in listDouble
                             group id by id into g
                             orderby g.Count() descending
                             select new { Id = g.Key, Count = g.Count() };


                foreach (var x in result)
                {
                    XuatHien Item = new XuatHien();
                    Item.TenThuocTinh = x.Id.ToString(); //số 
                    Item.SoLanXuatHien = x.Count; //số lần xuất hiện.
                    listResult.Add(Item);
                }
            }
            catch { }
            return listResult;
        }
        #endregion

        #region "[Điền dữ liệu còn thiếu]"
        /// <summary>
        /// điền dữ liệu còn thiếu
        /// </summary>
        /// <param name="_strContent">nội dung dữ liệu</param>
        /// <returns></returns>
        public override List<Cot> DienGiaTriBiThieu(List<Cot> _listCot)
        {
            List<Cot> listCots = new List<Cot>();
            try {
                foreach (Cot Itemi in _listCot)
                {
                    foreach (DoiTuong Itemj in Itemi.PhanTu)
                    {
                        if (Itemj.TenDoiTuong.Trim().CompareTo("?") == 0)
                        { 
                            //kiểm tra xem kiểu đối tuong là gì.
                            if (Itemi.KieuDuLieu == KieuDuLieu.Numeric)
                            { 
                                List<double> dLists= Itemi.PhanTu.Where (p=>p.TenDoiTuong.Trim().CompareTo("?")!=0).Select(p=>double.Parse( p.TenDoiTuong)).ToList();
                                Itemj.TenDoiTuong = TrungBinhCong(dLists).ToString();
                            }
                            else if (Itemi.KieuDuLieu == KieuDuLieu.Nominal)
                            {
                                Itemj.TenDoiTuong = TimThuocTinhXuatHienNhieuNhat(Itemi.PhanTu);
                            }
                        }
                    }
                }
                //gán mảng kết quả
                listCots = _listCot;
            }
            catch { }
            return listCots;
        }
        #endregion

        #region "[Đếm số lượng thuộc tính bị thiếu trong một cột]"
        /// <summary>
        /// Đếm số lượng thuộc tính bị thiếu trong một cột
        /// </summary>
        /// <param name="_cot">đối tượng cột</param>
        /// <returns></returns>
        public override int DemSoLuongGiaTriBiThieuTrongMotCot(Cot _cot)
        {
            int iResult = 0;
            try {
                foreach (DoiTuong Item in _cot.PhanTu)
                {
                    if (Item.TenDoiTuong.Trim().CompareTo("?") == 0)
                        iResult++;
                }
            }
            catch { }

            return iResult;
        }
        #endregion

        #region "[đếm số giá trị khác nhau trên 1 cột]"
        /// <summary>
        /// đếm số giá trị khác nhau trên 1 cột
        /// </summary>
        /// <param name="_cot">thông tin trên 1 cột</param>
        /// <returns></returns>
        public override int DemSoGiaTriKhacNhauTrongMotCot(Cot _cot)
        {
            int iResult = 0;
            try {
                iResult = TimTanSoXuatHienCuaDoiTuong(_cot.PhanTu).Count;
               
            }
            catch { }
            return iResult;
        }
        #endregion

        #region "[số mẫu không có giá trị trùng với các mẫu khác]"
        /// <summary>
        /// số mẫu không có giá trị trùng với các mẫu khác
        /// </summary>
        /// <param name="_cot"></param>
        /// <returns></returns>
        public override int DemSoMauKhongCoGiaTriTrungVoiMauKhac(Cot _cot)
        {
            int iResult = 0;
            try
            {
                iResult = TimTanSoXuatHienCuaDoiTuong(_cot.PhanTu).Where(p => p.SoLanXuatHien == 1).Count();

            }
            catch { }
            return iResult;
        }
        #endregion

        #region "[Bỏ các thuộc tính vào giỏ hàng]"
        /// <summary>
        /// bỏ các thuộc tính vào giỏ hàng
        /// </summary>
        /// <param name="_listInput"></param>
        /// <param name="_Phantu"></param>
        /// <returns></returns>
        private Gio BoVaoGioHang(Gio _gioEmpty, List<DoiTuong> _listDoiTuong)
        {
            Gio objResult = new Gio();
            _gioEmpty.SoLuong = 0;
            try {
                foreach (DoiTuong Item in _listDoiTuong)
                {
                    double giatri = double.Parse(Item.TenDoiTuong.Trim());
                    if (giatri >= _gioEmpty.GioiHanDuoi && giatri < _gioEmpty.GioiHanTren)
                    {
                        _gioEmpty.SoLuong++;
                        _gioEmpty.ListTenHoacGiaTri.Add(Item.TenDoiTuong);
                    }
                }
                objResult = _gioEmpty;
            }
            catch { }
            return objResult;

        }
        #endregion

        #region "[tìm độ lệch chuẩn]"
        /// <summary>
        /// tìm độ lệch chuẩn
        /// </summary>
        /// <param name="_doiTuong">danh sách các đối tượng</param>
        /// <returns></returns>
        public override double TimDoLechChuan(List<double> _listInput)
        {
            double dResult = 0;
            try {
                dResult = (1.0 / (_listInput.Count - 1));

                double AVG = TimGiaTriTrungBinh(_listInput);

                double Tong = 0;
                foreach (double Item in _listInput)
                {
                    Tong += Math.Pow(Item - AVG, 2.0);
                }
                //do lech chuan
                dResult = Math.Sqrt((dResult * Tong));
            }
            catch { }
            return dResult;
        }
        #endregion

        #region "[Tìm giá trị lớn nhất]"
        /// <summary>
        /// tìm giá trị lớn nhất
        /// </summary>
        /// <param name="_doiTuong">danh sách các đối tượng</param>
        /// <returns></returns>
        public override double TimGiaTriLonNhat(List<double> _listInput)
        {
            double dResult = 0;
            try
            {
                dResult = _listInput.Max();
            }
            catch { }
            return dResult;
        }
        #endregion

        #region "[Tìm giá trị nhò nhất]"
        /// <summary>
        /// tìm giá trị nhò nhất
        /// </summary>
        /// <param name="_doiTuong">danh sách các đối tượng</param>
        /// <returns></returns>
        public override double TimGiaTriNhoNhat(List<double> _listInput)
        {
            double dResult = 0;
            try
            {
                dResult = _listInput.Min();
            }
            catch { }
            return dResult;
        }
        #endregion

        #region "[Tìm giá trị trung bình]"
        /// <summary>
        /// tìm giá trị trung bình
        /// </summary>
        /// <param name="_doiTuong">danh sách các đối tượng</param>
        /// <returns></returns>
        public override double TimGiaTriTrungBinh(List<double> _listInput)
        {
            double dResult = 0;
            try
            {
                dResult = ((1.0 * _listInput.Sum()) / _listInput.Count);
            }
            catch { }
            return dResult;
        }
        #endregion

        #region "[Thống kê các thuộc tính trên 1 cột]"
        /// <summary>
        /// Thống kê các thuộc tính trên 1 cột
        /// <para>Giá trị lớn nhất</para>
        /// <para>Giá trị nhỏ nhất</para>
        /// <para>Giá trị trung bình</para>
        /// <para>Giá trị độ lệch chuẩn</para>
        /// </summary>
        /// <param name="_cot">cột thuộc tính</param>
        /// <returns></returns>
        public override ThongKeTrenCotNumeric ThongKeCacThuocTinhTrenCot(Cot _cot)
        {
            ThongKeTrenCotNumeric objResult = null;
            try {
                objResult = new ThongKeTrenCotNumeric();
                if (_cot.KieuDuLieu == KieuDuLieu.Numeric)
                {
                    List<double> listGiaTri = new List<double>();
                    if (_cot.PhanTu.Where(p => p.TenDoiTuong.CompareTo("?") == 0).ToList().Count < 1)
                    {
                      listGiaTri =  _cot.PhanTu.Select(p => double.Parse(p.TenDoiTuong)).ToList();
                    }
                    else
                    {
                        listGiaTri = _cot.PhanTu.Where(p => p.TenDoiTuong.CompareTo("?") != 0)
                            .Select(p => double.Parse(p.TenDoiTuong)).ToList();
                    }
                    objResult.Max = TimGiaTriLonNhat(listGiaTri);
                    objResult.Min = TimGiaTriNhoNhat(listGiaTri);
                    objResult.Mean = TimGiaTriTrungBinh(listGiaTri);
                    objResult.StdDev = TimDoLechChuan(listGiaTri);
                }
            }
            catch { }
            return objResult;
        }
        #endregion

        #region "[Đếm số lượng phần từ trong mảng xuất hiện]"
        /// <summary>
        /// Đếm số lượng phần từ trong mảng xuất hiện
        /// </summary>
        /// <param name="_vt">vị trí cần tính</param>
        /// <param name="_list">mảng đối tượng input</param>
        /// <returns></returns>
        public int Count(int _vt,List<XuatHien> _list)
        {
            int iResult = 0;
            try {
                for (int i = _vt; i < _list.Count; i++)
                {
                    iResult += _list[i].SoLanXuatHien;
                }
            }
            catch { }
            return iResult;
        }
        #endregion

        #region "[chia giỏ thuộc tính theo chiều rộng và theo chiều sâu]"
        /// <summary>
        /// chia giỏ thuộc tính theo chiều rộng và theo chiều sâu
        /// Một cột có nhiều giỏ
        /// Một bảng có nhiều cột
        /// </summary>
        /// <param name="_cots">danh sách các cột chứa dữ liệu trong bảng (bỏ cột tiêu đề)</param>
        /// <param name="_SoLuongGio">số lượng giỏ cần chia</param>
        /// <param name="_kieuChia">kiểu chia</param>
        /// <returns></returns>
        public override List<NhomGio> ChiaGioThuocTinh(List<Cot> _cots,int _SoLuongGio, KieuChia _kieuChia)
        {
            ///Danh sách các nhóm giỏ chia được
            ///Lưu ý mỗi nhóm giỏ tương ứng với 1 cột
            List<NhomGio> listResult = new List<NhomGio>();
            try {
                switch (_kieuChia)
                { 
                    case KieuChia.TheoChieuRong:
                        #region "[Chia theo chiều rộng]"
                        //chia dữ liệu theo chiều rộng
                        foreach (Cot Item in _cots)
                        {
                            ///nếu kiều dữ liệu là nominal thì ta thực hiện chia dữ liệu theo kiểu:
                            ///gom nhóm từng phần tử lại rồi đến số lượng
                            if (Item.KieuDuLieu == KieuDuLieu.Nominal)
                            {
                                #region "[khai báo 1 nhóm giỏ cho cột này.]"
                                NhomGio nhomGioInfo = GomNhomVaDemSoLuong(Item);
                                listResult.Add(nhomGioInfo);
                                #endregion
                            }
                            //kiểm tra nếu cột là kiểu số thì thực hiện chia giỏ theo số lượng giỏ khách hàng nhập vào
                            else if (Item.KieuDuLieu == KieuDuLieu.Numeric)
                            {
                                #region "[Chia theo chiều rộng với dữ liệu là số]"
                                //khai báo nhóm giỏ cho cột này
                                NhomGio nhomGioInfo = new NhomGio();
                                nhomGioInfo.KieuDuLieu = KieuDuLieu.Numeric;

                                //sắp xếp giá trị các thuộc tính trong 1 cột tăng dần.
                                List<DoiTuong> listThuocTinhs = Item.PhanTu.Where(p=>p.TenDoiTuong.Trim().CompareTo("?")!=0).OrderBy(p => double.Parse(p.TenDoiTuong)).ToList();

                                //giá trị nhỏ nhất.
                                double Min =  double.Parse(listThuocTinhs[0].TenDoiTuong);

                                //tính độ rộng của từng khoản.
                                double doRongTinhKhoang =(double) ((double.Parse(listThuocTinhs[listThuocTinhs.Count - 1].TenDoiTuong) - 
                                    Min)/_SoLuongGio);
                                double ddoRongTinhKhoang = Math.Round(doRongTinhKhoang, 0);

                                //tìm được số lượng giá trị trong một giỏ.
                                double SoLuongGiaTriTrongGio = ddoRongTinhKhoang;
                                if (SoLuongGiaTriTrongGio == 0)
                                {
                                    SoLuongGiaTriTrongGio = doRongTinhKhoang;
                                }
                                
                                ///Khai báo 2 biến tạm lưu giới hạn trên và giới hạn dưới của 1 giỏ thuộc tính
                                double Max = Min;
                                for (int i = 0; i < _SoLuongGio; i++)
                                {
                                    Min = Max;
                                    Max = Min+SoLuongGiaTriTrongGio;
                                    
                                    //khai báo Giỏ
                                    Gio gioInfo = new Gio();
                                    gioInfo.SoLuong = 0;
                                    gioInfo.GioiHanDuoi = Min;
                                    gioInfo.GioiHanTren = Max;
                                    if (i == _SoLuongGio - 1)
                                        gioInfo.GioiHanTren++;
                                    //thêm vào nhóm giỏ
                                    nhomGioInfo.GioThuocTinhs.Add(gioInfo);
                                }
                                //khai báo biến nhóm giỏ đề lưu giá trị cuối cùng.
                                NhomGio nhomGioInfoFull = new NhomGio();
                                //Duyệt từng giỏ hàng và tìm số lượng và danh sách các thuộc tính bên trong nó.
                                foreach (Gio gioItem in nhomGioInfo.GioThuocTinhs)
                                {
                                    Gio gioItemfull = BoVaoGioHang(gioItem, Item.PhanTu.Where(p => p.TenDoiTuong.Trim().CompareTo("?") != 0).ToList());
                                    nhomGioInfoFull.KieuDuLieu = KieuDuLieu.Numeric;
                                    nhomGioInfoFull.GioThuocTinhs.Add(gioItemfull);

                                }
                                listResult.Add(nhomGioInfoFull);
                                #endregion 
                            }
                        }
                        #endregion
                        break;
                    case KieuChia.TheoChieuSau:
                       
                        //chia dữ liệu theo chiều sâu
                        //chia dữ liệu theo chiều rộng
                        foreach (Cot Item in _cots)
                        {
                            ///nếu kiều dữ liệu là nominal thì ta thực hiện chia dữ liệu theo kiểu:
                            ///gom nhóm từng phần tử lại rồi đến số lượng
                            if (Item.KieuDuLieu == KieuDuLieu.Nominal)
                            {
                                #region "[khai báo 1 nhóm giỏ cho cột này.]"
                                //khai báo 1 nhóm giỏ cho cột này.
                                NhomGio nhomGioInfo = GomNhomVaDemSoLuong(Item);
                                listResult.Add(nhomGioInfo);
                                #endregion
                            }
                            //kiểm tra nếu cột là kiểu số thì thực hiện chia giỏ theo số lượng giỏ khách hàng nhập vào
                            else if (Item.KieuDuLieu == KieuDuLieu.Numeric)
                            {
                               //chia dữ liệu theo độ sâu.
                                
                                //khai báo nhóm giỏ
                                NhomGio nhomGioItem = new NhomGio();
                                nhomGioItem.KieuDuLieu = KieuDuLieu.Numeric;
                                
                                //lấy danh sách các thuộc tính được sắp xếp tăng dần.
                                List<DoiTuong> listDoiTuongTemps = Item.PhanTu.Where(p => p.TenDoiTuong.Trim().CompareTo("?") != 0).OrderBy(p => double.Parse(p.TenDoiTuong)).ToList();

                                //gom nhóm các đối tượng
                                List<XuatHien> listXuatHienNumeric = GomNhomDoiTuongKieuNumeric(listDoiTuongTemps);
                                listXuatHienNumeric = listXuatHienNumeric.OrderBy(p => double.Parse(p.TenThuocTinh)).ToList();

                                ///nếu mảng danh sách các đói tượng còn phần tử thì tiếp tục xử lý
                                int soLuongGioCanChia =  _SoLuongGio;
                                List<Gio> gios = new List<Gio>();
                                for (int i = 0; i < _SoLuongGio; i++)
                                {
                                    Gio ItemInsertGio = new Gio();
                                    gios.Add(ItemInsertGio);
                                }
                                int vt = 0;
                                int k = 0;
                                //giới hạn các phần tử trong giỏ
                                int gioiHanGio = 0;
                                bool flag = false;
                                int DoSauGioHang = 0;
                                for (int i = vt; i < listXuatHienNumeric.Count; i++)
                                {
                                   
                                    

                                    //tìm độ sâu giỏ.
                                    if (!flag)
                                    {
                                        //số lượng phần tử hiện tại
                                        int SoLuongPhanTuHienTai = Count(vt, listXuatHienNumeric);
                                        DoSauGioHang = (int)Math.Round((1.0 * SoLuongPhanTuHienTai / soLuongGioCanChia), 0);
                                    }

                                    int soLanXuatHienInfo = listXuatHienNumeric[i].SoLanXuatHien;
                                    string tenThuocTinhInfo = listXuatHienNumeric[i].TenThuocTinh;
                                    
                                    if (i == 0)
                                    {
                                        gioiHanGio = soLanXuatHienInfo;
                                        //tìm giới hạn dưới của thuộc tính
                                        gios[k].GioiHanDuoi = double.Parse(tenThuocTinhInfo);
                                        gios[k].SoLuong++;
                                        gios[k].ListTenHoacGiaTri.Add(tenThuocTinhInfo);
                                        flag = true;
                                    }
                                    else
                                    { 
                                        //nếu i>0
                                        //kiểm tra giới hạn thuộc tính lúc sau.
                                        if ((gioiHanGio + soLanXuatHienInfo) > DoSauGioHang)
                                        {
                                            //cập nhật giới hạn trên
                                            gios[k].GioiHanTren = double.Parse(tenThuocTinhInfo);

                                            //nếu lớn hơn giới hạn thì lưu phần tử này vào giỏ tiếp theo.
                                            if (soLuongGioCanChia > 0)
                                                k++;
                                            gios[k].GioiHanDuoi = double.Parse(tenThuocTinhInfo);
                                            gios[k].ListTenHoacGiaTri.Add(tenThuocTinhInfo);

                                            soLuongGioCanChia = _SoLuongGio - (k + 1);
                                            
                                                gioiHanGio = soLanXuatHienInfo;
                                            if (gioiHanGio > DoSauGioHang)
                                                flag = false;
                                            else
                                                flag = true;
                                        }
                                        else {
                                            gioiHanGio += soLanXuatHienInfo;
                                            //nếu vẫn không nhỏ hơn thì thêm tiếp vào giỏ.
                                            gios[k].GioiHanTren = double.Parse(tenThuocTinhInfo);
                                            gios[k].ListTenHoacGiaTri.Add(tenThuocTinhInfo);
                                            gios[k].GioiHanTren = double.Parse(tenThuocTinhInfo);
                                            flag = true;
                                        }
                                    }

                                    vt++;
                                }
                                //cập nhật số lượng giỏ trong nhóm giỏ.
                                gios = CapNhatDanhSachGio(gios, listXuatHienNumeric);

                                nhomGioItem.GioThuocTinhs = gios;
                                listResult.Add(nhomGioItem);
                                //while (vt <soLuongGioCanChia)
                                //{
                                    
                                //    int jrun = 0;//cho biến chạy đến giới hạn là độ sâu hiện tại của giỏ hàng
                                //    //tính độ sâu của từng giỏ.
                                //   int DoSauGioHang = (int)Math.Round( (1.0*listDoiTuongTemps.Count/soLuongGioCanChia),0);

                                //   //Gio[] ItemGioHang = new Gio[_SoLuongGio];
                                //    List<Gio>ItemGioHang = new List<Gio>();
                                //    //for (int i = 0; i < _SoLuongGio; i++)
                                //    //{
                                //    //    Gio jItem = new Gio();
                                //    //    ItemGioHang.Add(jItem);
                                //    //}
                                //   //int k = 0;
                                //   // for (int i = k; i < listDoiTuongTemps.Count; i++)
                                //   // {
                                //   //     string TenDoiTuongInfo = listDoiTuongTemps[i].TenDoiTuong;
                                //   //     if (jrun == 0)
                                //   //     {
                                //   //         //ItemGioHang[vt] = new Gio();
                                //   //         ItemGioHang[vt].GioiHanDuoi = double.Parse(TenDoiTuongInfo);
                                //   //     }
                                //   //     ItemGioHang[vt].ListTenHoacGiaTri.Add(TenDoiTuongInfo);
                                //   //     ItemGioHang[vt].GioiHanTren = double.Parse(TenDoiTuongInfo);
                                //   //     ItemGioHang[vt].SoLuong++;
                                //   //     //listDoiTuongTemps.Remove(listDoiTuongTemps[i]);
                                //   //     jrun++;
                                //   //     if (jrun == DoSauGioHang)
                                //   //     {
                                //   //         jrun = 0;
                                //   //         vt++;
                                //   //         soLuongGioCanChia--;
                                //   //         k = DoSauGioHang;
                                //   //     }
                                //   // }
                                //    //nhomGioItem.GioThuocTinhs = ItemGioHang.ToList();
                                //    //listResult.Add(nhomGioItem);
                                //}

                            }
                        }
                        break;
                }
            }
            catch { }
            return listResult;
        }

        private List<Gio> CapNhatDanhSachGio(List<Gio> gios, List<XuatHien> listXuatHienNumeric)
        {
            List<Gio> listResult = new List<Gio>();
            try {
                foreach (Gio Item in gios)
                {
                    Item.SoLuong = TinhSoLuong(Item.ListTenHoacGiaTri, listXuatHienNumeric);
                    listResult.Add(Item);
                }
            }
            catch { }
            return listResult;
        }

        private int TinhSoLuong(List<string> list, List<XuatHien> listXuatHienNumeric)
        {
            int iResult = 0;
            try {
                foreach (XuatHien Item1 in listXuatHienNumeric)
                {
                    foreach (string s in list)
                    {
                        if (double.Parse(s) == double.Parse(Item1.TenThuocTinh))
                            iResult += Item1.SoLanXuatHien;
                    }
                }
            }
            catch { }
            return iResult;
        }

        #endregion

        #region "[Gom nhóm và đến số lượng]"
        /// <summary>
        /// Gom nhóm và đến số lượng
        /// </summary>
        /// <param name="Item"></param>
        /// <returns></returns>
        private NhomGio GomNhomVaDemSoLuong(Cot Item)
        {
            //khai báo 1 nhóm giỏ cho cột này.
            NhomGio nhomGioInfo = new NhomGio();
            nhomGioInfo.KieuDuLieu = KieuDuLieu.Nominal;

            ///Lấy thông tin tần số xuất hiện của từng thuộc tính
            List<XuatHien> TanSoXuatHien = TimTanSoXuatHienCuaDoiTuong(Item.PhanTu);
            foreach (XuatHien ItemXH in TanSoXuatHien)
            {
                Gio gioInfo = new Gio();
                gioInfo.TenHoacGiaTri = ItemXH.TenThuocTinh;
                gioInfo.SoLuong = ItemXH.SoLanXuatHien;

                //thêm vào nhóm giỏ của cột này.
                nhomGioInfo.GioThuocTinhs.Add(gioInfo);
            }
            return nhomGioInfo;
        }
        #endregion

        #region "[Chuẩn hóa dữ liệu có kiểu numeric]"
        /// <summary>
        /// <para>Chuẩn hóa dữ liệu có kiểu numeric</para>
        /// <para>Bao Gồm: </para>
        /// <para>*) Chuẩn hóa min max</para>
        /// <para>*) Chuẩn hóa z-score</para>
        /// </summary>
        /// <param name="_cots">danh sách các cột</param>
        /// <param name="_dMin">giá trị nhỏ nhất</param>
        /// <param name="_dMax">giá trị lớn nhất</param>
        /// <param name="_kieuChuanHoa">kiểu chuẩn hóa</param>
        /// <returns></returns>
        public override List<ChuanHoaDuLieu> ChuanHoaThuocTinhCoKieuNumberic(List<Cot> _cots, double _dMin, double _dMax,KieuChuanHoa _kieuChuanHoa)
        {
            List<ChuanHoaDuLieu> listObjectResult = new List<ChuanHoaDuLieu>();
            try {
                
                if (_kieuChuanHoa == KieuChuanHoa.MIN_MAX)
                {
                    //thực hiện chuẫn hóa theo kiểu min Max
                    foreach (Cot Item in _cots)
                    {
                        if (Item.KieuDuLieu == KieuDuLieu.Numeric)
                        {
                            //chỉ xử lý đối với dữ liệu số
                            List<double> dLists = Item.PhanTu.Where(p => p.TenDoiTuong.CompareTo("?") != 0).Select(p => double.Parse(p.TenDoiTuong)).ToList();

                            //tìm giá trị lớn nhất và nhỏ nhất của dữ liệu
                            double Max = TimGiaTriLonNhat(dLists);
                            double Min = TimGiaTriNhoNhat(dLists);

                            //danh sách kết quả
                            List<double> dListResult = new List<double>();
                            foreach (double ItemIrun in dLists)
                            {
                                double dTemp = (((ItemIrun - Min) / (Max - Min)) * (_dMax - _dMin) + _dMin);
                                dListResult.Add(dTemp);
                            }
                            ChuanHoaDuLieu objResult = new ChuanHoaDuLieu();
                            objResult.Max = _dMax;
                            objResult.Min = _dMin;
                            objResult.Mean = TimGiaTriTrungBinh(dListResult);
                            objResult.StdDev = TimDoLechChuan(dListResult);
                            listObjectResult.Add(objResult);
                        }
                        else
                        { 
                           listObjectResult.Add(new ChuanHoaDuLieu());
                        }
                    }
                }
                else
                {
                    if (_kieuChuanHoa == KieuChuanHoa.Z_SCORE)
                    {
                        foreach (Cot Item in _cots)
                        {
                            if (Item.KieuDuLieu == KieuDuLieu.Numeric)
                            {
                                //chỉ xử lý đối với dữ liệu số
                                List<double> dLists = Item.PhanTu.Where(p => p.TenDoiTuong.CompareTo("?") != 0).Select(p => double.Parse(p.TenDoiTuong)).ToList();

                                //tìm giá trị trung bình của A
                                double Avg = TimGiaTriTrungBinh(dLists);
                                double stdDev = TimDoLechChuan(dLists);

                                //danh sách các kết quả
                                List<double> listResult = new List<double>();
                                foreach (double ItemIrun in dLists)
                                {
                                    listResult.Add((ItemIrun - Avg) / stdDev);
                                }
                                ChuanHoaDuLieu objResult = new ChuanHoaDuLieu();
                                objResult.Max = TimGiaTriLonNhat(listResult);
                                objResult.Min = TimGiaTriNhoNhat(listResult);
                                objResult.Mean = TimGiaTriTrungBinh(listResult);
                                objResult.StdDev = TimDoLechChuan(listResult);

                                listObjectResult.Add(objResult);
                            }
                        }
                    }
                    else
                    {
                        listObjectResult.Add(new ChuanHoaDuLieu());
                    }
                }
            }
            catch { }
            return listObjectResult;
        }
        #endregion

        #region "[ghi file]"
        /// <summary>
        /// gh thông tin file csv
        /// </summary>
        /// <param name="_strContent">nội dung file cần ghi</param>
        /// <param name="_strPath">đường dẫn file cần ghi</param>
        /// <returns></returns>
        public override bool GhiFile(List<string> _strContent, string _strPath)
        {
            bool isSuccess = false;
            try {
                StreamWriter writer = new StreamWriter(_strPath);
                foreach (string Item in _strContent)
                {
                    writer.WriteLine(Item);
                }
                
                writer.Flush();
                writer.Close();
                isSuccess = true;
            }
            catch { }
            return isSuccess;
        }
        #endregion

    }
}
